// 这个程序就是为了处理我自己的大气校正产品AC或者植被指数产品NDVI，对这个产品做云和云阴影的去除。
// 云和云阴影在其他程序进行生成，作为一个产品一个输入在这里使用（CS）。
// 对于CS数据有三个值：0-未检测，1-云，2-阴影。
// 对于输入数据，逐像素检查CS像素值：0保留输出（几个通道都支持），1和2都使用填充值。
// 2024/6/21

#include <memory>
#include <iostream>
#include "gdal_priv.h"
#include <vector>
#include <string>
#include "getopt_pp.h"
#define WGDALRASTER_H_IMPLEMENTATION
#include "../sharedcodes/wGdalRaster.h"
using namespace GetOpt;
using namespace std;
const int PIXEL_VALUE_CLEAR=0;
const int PIXEL_VALUE_CLOUD=1;
const int PIXEL_VALUE_SHADOW=2;




int main(int argc,char* argv[])
{
    cout << "A program to fill out the cloud(1) and shadow(2) pixels for input data." << endl;
    cout<<"version v1.0.0.0 2024/6/21"<<endl;
    cout << "usage:mask_out_cloudNshadows -f fillvalue -i input.tif -c cloudNshadow.tif -o output.tif " << endl;
    cout<<"  -i input and cloudNshadows data must same size. support multibands."<<endl;
    cout<<"  -o output has same size and bands as input."<<endl;
    GDALAllRegister();
    GetOpt_pp ops(argc, argv);
    
    string infilename  ;
    string cloudfilename ;//cloud and shadows 
    string outfilename ;
    double fillvalue = -9999 ;

    ops >>Option('i',infilename)
        >>Option('o', outfilename) 
        >>Option('c',cloudfilename)   
        >>Option('f',fillvalue)   
        ;

    cout << "input:" << endl;
    cout << "infilename "<< infilename <<endl;
    cout << "cloudfilename " << cloudfilename << endl;
    cout << "outfilename " << outfilename << endl;
    cout << "fillvalue " << fillvalue << endl;
    if( infilename=="") {
        cout<<"bad infilename "<<endl ;
        return 11 ;
    }
    if( cloudfilename=="") {
        cout<<"bad cloudfilename "<<endl ;
        return 11 ;
    }
    if( outfilename=="") {
        outfilename = infilename + "_maskcs.tif" ;
        cout<<"using outfilename "<<outfilename<<endl;
    }

    shared_ptr<wGdalRaster> inRaster( wGdalRasterFactory::OpenFile(infilename) );
    if (inRaster.get() == 0) {
        cout << "failed to open " << infilename;
        return 12;
    }

    int xsize = inRaster->getXSize();
    int ysize = inRaster->getYSize();
    int asize = xsize * ysize;
    int nband = inRaster->getNBand() ;
    
    wGdalRasterByte cloudShadows;
    bool csOk = cloudShadows.open(cloudfilename) ;
    if( csOk==false) {
        cout<<"failed to open "<<cloudfilename<<endl;
        return 12 ;
    }
    if( xsize!= cloudShadows.getXSize() ) {
        cout<<"input xsize not equal with cloudNshadow xsize."<<endl;
        return 13 ;
    }
    if( ysize!= cloudShadows.getYSize() ) {
        cout<<"input ysize not equal with cloudNshadow ysize."<<endl;
        return 13 ;
    }

    for(int it = 0 ;it < asize; ++ it ) {
        int csvalue = cloudShadows.getValuei(it , 0 );
        if( csvalue == PIXEL_VALUE_CLOUD || csvalue==PIXEL_VALUE_SHADOW ) {
            for(int ib = 0 ; ib<nband;++ib ) {
                inRaster->setValued(it,ib,fillvalue) ;
            }
        }
    }

    bool saveok = inRaster->save(outfilename) ;
    if( saveok==false ) {
        cout<<"save failed "<<outfilename<<endl;
        return 20 ;
    }
    cout << "done" << endl;
    return 0;
}


